FE-755: Cook codebase mode for brownfield brunch#155
Conversation
brunch cook.brunch cook
PR SummaryMedium Risk Overview Cook output moves from
Reviewed by Cursor Bugbot for commit ea21ecf. Bugbot is set up for automated code reviews on this repo. Configure here. |
|
Warning This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
This stack of pull requests is managed by Graphite. Learn more about stacking. |
🤖 Augment PR SummarySummary: This PR implements “codebase mode” for Changes:
Technical notes: Codebase mode checks out a separate worktree branch ( 🤖 Was this summary useful? React with 👍 or 👎 |
4e77df6 to
c2cfb6e
Compare
ee16289 to
eef2f05
Compare
brunch cookc2cfb6e to
e549e84
Compare
eef2f05 to
578e7c9
Compare
e549e84 to
ecc2cc5
Compare
921cb17 to
2047ef2
Compare
ecc2cc5 to
3cc97a2
Compare
3cc97a2 to
92ac186
Compare
2047ef2 to
525fd4d
Compare
525fd4d to
89a128a
Compare
92ac186 to
4fef9e7
Compare
|
Fixed in bd95f3a: |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit bd95f3a. Configure here.
`brunch cook <dir>` now runs against an existing repo. When `<dir>/.brunch/cook/plan.yaml` exists and the working tree's tracked files are clean, cook initializes the sandbox via `git worktree add <sandboxDir> -b cook/<runId> HEAD` from the source repo, per-slice worktrees are seeded by file-copy from the parent (excluding `.git`, sibling slice dirs, and `__epic__/`), and pi-actions run unchanged against pre-existing code. The source branch in `<dir>` stays byte-identical. Also consolidates cook's filesystem footprint from `<cwd>/.cook/` to `<cwd>/.brunch/cook/` so all cook state lives under the existing `.brunch/` workspace convention. Acceptance criteria covered: - Resolver replaces the "not yet implemented" early-exit at cook-cli.ts:65-70 with a pure `resolveCookMode(dir)` discriminated union (fixture / codebase / error). - Clean-tree gate refuses brownfield runs with uncommitted tracked changes (`git status --porcelain --untracked-files=no`). - `createSandbox` gains a `CreateSandboxOptions` discriminated union; codebase mode invokes `git worktree add` on branch `cook/<runId>`. - `seedSliceFromParentWorktree` populates per-slice dirs from the parent worktree contents. - `OrchestratorInput.sandboxMode?: 'fixture' | 'codebase'` threads the mode through to net-compiler. - `pi-actions.ts` unchanged. Existing greenfield fixture-mode tests pass; new tests in cook-cli.test.ts (resolveCookMode), worktree.test.ts (codebase-mode createSandbox), epic-sandbox-merge.test.ts (seedSliceFromParentWorktree), plus a tmpdir+fake-actions brownfield-smoke.integration.test.ts that pins source-byte-identical isolation. Total: 1447/1447 tests pass. Known follow-ons (out of scope for this PR): - pi-actions evaluator currently gets full write tools, collapsing the TDD-shaped workflow when pi can satisfy the slice during evaluation. - No "promote cook artifact back" story — modification lives in untracked subdirs of the cook branch's worktree, not as commits. - Multi-slice brownfield over-copy (TODO in `seedSliceFromParentWorktree`) — slice 2's 1-slice fixture didn't exercise it. A 2026-05-26 spike evaluated `@ai-hero/sandcastle` for hybrid adoption. Technically viable (built-in pi provider, decoupled worktree primitives, noSandbox available) but deferred until sandcastle ships 1.0 or multi-slice over-copy becomes a measurable bottleneck. A 2026-05-26 outer-loop smoke against a tmpdir git repo with real pi confirmed in-place file modification and source-byte-identical isolation end-to-end. Updates SPEC §D50, §A49, §I123-K, §Lexicon (path consolidation) and PLAN.md `cook-codebase-mode` frontier definition (now Recently Completed with three follow-on findings). Co-Authored-By: Claude <noreply@anthropic.com>
Slice 3 of FE-755 refactors per-slice worktree population into a hybrid mechanism. Tracked content arrives via `git worktree add` on a slice-level branch (`cook-slice/<runId>/<sliceId>`); untracked/gitignored content (`node_modules/`, `dist/`, etc.) arrives via copy-on-write (`cp -c` on macOS APFS, `cp --reflink=auto` on Linux btrfs/xfs/zfs, recursive `cpSync` fallback). Solves the multi-slice over-copy problem flagged as a TODO in slice 2 (~90% disk savings on CoW filesystems) while keeping runtime deps present so pi-actions can run `npm test`/`bun test` against the slice worktree. Slice branches use the `cook-slice/<runId>/<sliceId>` sibling namespace rather than nesting under `cook/<runId>/<sliceId>` because git refs are leaf-or-directory: with `cook/<runId>` already a leaf, the nested form fails with "cannot lock ref ... 'refs/heads/cook/<runId>' exists." OrchestratorInput.runId threads through from cook-cli for slice-branch naming. pi-actions.ts unchanged. Test changes: - epic-sandbox-merge.test.ts: rewrites seedSliceFromParentWorktree tests around real git parents — tracked-via-git, untracked-via-CoW, slice-level branch checkout, sibling-slice exclusion, __epic__ exclusion. - brownfield-smoke.integration.test.ts: passes runId; asserts the slice worktree is on its cook-slice/<runId>/<sliceId> branch. - Verify: 123 test files, 1449 tests pass; 0 errors. Also: docs/praxis/cook-brownfield.md — brunch-specific operational guide covering pre-flight, hand-authored vs ln-scope-derived plans, the absolute-path invocation gotcha, source-byte-identical verification, manual artifact promotion, and cleanup. PLAN.md updated: the multi-slice over-copy follow-on is retired (subsumed by this work). `cook-artifact-lifecycle` remains as a separate proposed frontier: commit slice work, replace mergeSlicesIntoEpicSandbox's file-copy with `git merge` of slice branches (surfaces real conflicts; today's behavior is silent last-slice-wins), and merge epic branches back to cook/<runId> so `git merge cook/<runId>` becomes the promotion path. This slice sets up the substrate (real slice branches) so that frontier can land cleanly on top. Co-Authored-By: Claude <noreply@anthropic.com>
…tion. Renames docs/praxis/cook-brownfield.md → docs/praxis/orchestration-guide.md to make room for the doc to grow beyond pure brownfield-mode notes (e.g. greenfield fixture workflows, future graph-compiled plans). Restructures the "Author the plan" section to lead with the intended long-term target: read the plan from a spec-graph projection emitted by `petri-graph-compilation` (currently blocked on FE-700 intent-graph- semantics). Until that lands, two interim bridges remain — `/ln-scope`- then-translate (most disciplined) and one-shot pi translation (cheap) — plus hand-authoring as an escape hatch for one-off experiments. Co-Authored-By: Claude <noreply@anthropic.com>
Fail before git worktree add when a slice id matches an existing top-level path in the parent worktree (e.g. src/). Co-authored-by: Cursor <cursoragent@cursor.com>
git worktree add only checks out tracked files; CoW-copy missing top-level entries from the source cwd when creating the parent sandbox so slice seeding inherits node_modules/dist-style artifacts. Extract cowCopy into cow-copy.ts with complete JSDoc and reuse for slice seed. Co-authored-by: Cursor <cursoragent@cursor.com>
When brunch cook runs against the current repo, copying .brunch would recursively duplicate prior run worktrees into the new sandbox.
Use the exported SandboxMode alias in sandbox creation options so the type is referenced at the public API seam. Co-authored-by: Cursor <cursoragent@cursor.com>
Codebase-mode slice worktrees carry a .git pointer file; walkFiles was copying it into __epic__ sandboxes and giving verify-epic the wrong git context. Skip .git/.brunch/__epic__ during merge and seed file walks. Co-authored-by: Cursor <cursoragent@cursor.com>
bd95f3a to
ea21ecf
Compare


Summary
resolveCookModeselects fixture vs codebase when.brunch/cook/plan.yamlis present, the tracked working tree is clean, and the target directory is a git repository.cook/<runId>and per-slice worktrees oncook-slice/<runId>/<sliceId>, with copy-on-write for untracked/gitignored content where the OS supports it..brunch/cook/runs/<runId>/(replacing.cook/); addsdocs/praxis/orchestration-guide.mdfor operators running cook on real repos.Context
brunch cookfrom fixture-only greenfield runs to brownfield repositories while keeping the user’s source branch byte-identical for the duration of a run.node_modules, build outputs): APFSclonefile, Linux reflink, thencpSyncfallback.pi-actions.ts) stays unchanged at the seam; only sandbox resolution and filesystem layout change.What changed
cowCopyseeds untracked/gitignored files into slice sandboxes without mutating the source checkout.brownfield-smoke.integration.test.tsplus a documented 2026-05-26 real-pi smoke on a temporary git repo.Verification
npm run verifygreen (1449 tests at PR time).Out of scope
cook-artifact-lifecyclefrontier).Traceability
cook-codebase-modeinmemory/PLAN.md; stacks on FE-747.